package fastHttpInvoker

import (
	"AiSpeaker/pkg/logger"
	"encoding/json"
	"github.com/valyala/fasthttp"
	"time"
)

func HttpGet(url string, args string, headers map[string]string, cookies map[string]string) ([]byte, error) {
	// 获取客户端
	client := getFastReqClient()
	// 从请求池中分别获取一个request、response实例
	req, resp := fasthttp.AcquireRequest(), fasthttp.AcquireResponse()
	// 回收实例到请求池
	defer func() {
		fasthttp.ReleaseRequest(req)
		fasthttp.ReleaseResponse(resp)
	}()
	// 设置请求方式
	req.Header.SetMethod(fasthttp.MethodGet)
	// 设置请求地址
	req.SetRequestURI(url)
	// 设置参数
	if args != "" {
		req.URI().SetQueryString(args)
	}

	// 设置header信息
	if headers != nil {
		for key, val := range headers {
			req.Header.Add(key, val)
		}
	} else {
		req.Header.Add("content-type", "application/json")
	}
	// 设置Cookie信息
	if cookies != nil {
		for key, val := range headers {
			req.Header.SetCookie(key, val)
		}
	}
	// 发起请求
	if err := client.Do(req, resp); err != nil {
		logger.Errorf("req err %v", err)
		return nil, err
	}
	// 读取结果
	return resp.Body(), nil
}

func HttpDelete(url string, args string, headers map[string]string, cookies map[string]string) ([]byte, error) {
	// 获取客户端
	client := getFastReqClient()
	// 从请求池中分别获取一个request、response实例
	req, resp := fasthttp.AcquireRequest(), fasthttp.AcquireResponse()
	// 回收实例到请求池
	defer func() {
		fasthttp.ReleaseRequest(req)
		fasthttp.ReleaseResponse(resp)
	}()
	// 设置请求方式
	req.Header.SetMethod(fasthttp.MethodDelete)
	// 设置请求地址
	req.SetRequestURI(url)
	// 设置参数
	if args != "" {
		req.URI().SetQueryString(args)
	}

	// 设置header信息
	if headers != nil {
		for key, val := range headers {
			req.Header.Add(key, val)
		}
	} else {
		req.Header.Add("content-type", "application/json")
	}
	// 设置Cookie信息
	if cookies != nil {
		for key, val := range headers {
			req.Header.SetCookie(key, val)
		}
	}
	// 发起请求
	if err := client.Do(req, resp); err != nil {
		logger.Errorf("req err %v", err)
		return nil, err
	}
	// 读取结果
	return resp.Body(), nil
}

/**
* @Description: post请求
* @Return string
**/
func HttpPost(url string, paramRaw any, headers map[string]string, cookies map[string]string) ([]byte, error) {
	// 获取客户端
	client := getFastReqClient()
	// 从请求池中分别获取一个request、response实例
	req, resp := fasthttp.AcquireRequest(), fasthttp.AcquireResponse()
	// 回收到请求池
	defer func() {
		fasthttp.ReleaseRequest(req)
		fasthttp.ReleaseResponse(resp)
	}()

	req.Header.Add("content-type", "application/json")
	// 设置header信息
	if headers != nil {
		for key, val := range headers {
			req.Header.Add(key, val)
		}
	}
	// 设置Cookie信息
	if cookies != nil {
		for key, val := range headers {
			req.Header.SetCookie(key, val)
		}
	}
	// 设置请求方式
	req.Header.SetMethod(fasthttp.MethodPost)
	// 设置请求地址
	req.SetRequestURI(url)
	// 设置请求ContentType
	req.Header.SetContentType("application/json")
	// 设置参数
	marshal, err := json.Marshal(paramRaw)
	if err != nil {
		return nil, err
	}
	req.SetBodyRaw(marshal)
	// 发起请求
	if err := client.Do(req, resp); err != nil {
		return nil, err
	}
	// 读取结果
	return resp.Body(), nil
}

func getFastReqClient() *fasthttp.Client {
	reqClient := &fasthttp.Client{
		// 读超时时间,不设置read超时,可能会造成连接复用失效
		ReadTimeout: time.Second * 5,
		// 写超时时间
		WriteTimeout: time.Second * 5,
		// 5秒后，关闭空闲的活动连接
		MaxIdleConnDuration: time.Second * 5,
		// 当true时,从请求中去掉User-Agent标头
		NoDefaultUserAgentHeader: true,
		// 当true时，header中的key按照原样传输，默认会根据标准化转化
		DisableHeaderNamesNormalizing: true,
		//当true时,路径按原样传输，默认会根据标准化转化
		DisablePathNormalizing: true,
		Dial: (&fasthttp.TCPDialer{
			// 最大并发数，0表示无限制
			Concurrency: 20,
			// 将 DNS 缓存时间从默认分钟增加到一小时
			DNSCacheDuration: time.Hour,
		}).Dial,
	}
	return reqClient
}
